package cn.tedu.review;
/*本类用于复写售票案例实现方案1*/
public class TestThread {
    public static void main(String[] args) {
        //5.创建多个自定义类对象作为多个线程对象,里面包含了我们的业务
        TicketThread t1 = new TicketThread();
        TicketThread t2 = new TicketThread();
        TicketThread t3 = new TicketThread();
        TicketThread t4 = new TicketThread();
        //6.以多线程的方式,启动多个线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();


    }
}

//1.自定义多线程类
class TicketThread extends Thread{

    //3.定义一个变量,用来保存票数
    /*将票数设置为静态,静态资源被本类的所有对象共享,值只有一份,解决卖400张票的问题*/
    static int tickets = 100; //静态的就唯一

//    static Object o= new Object(); //new
//    static Dog d = new Dog(); //如果没有static,就有很多个new Dog()...

    //2.重写父类run(),里面是我们自己的业务
    @Override
    public void run() {

        //4.循环卖票
        while(true){
//        synchronized (o){
            synchronized (TicketThread.class ){ // 唯一字节码解决重卖                      直接用唯一的字节码文件(排队),1)解决重卖情况(多线程/共享数据/多条语句操作共享数据)
//                if (tickets > 0) { //             两个并列if解决超卖                    0)经过同步字节码操作, 1)当多线程重复拿到同一张票时,两个并列if解决了,即使多次拿到1,底层或其它对接方只会处理第一个拿到1的多线程,超卖现象
                    //7.让线程休眠,增加线程状态切换的频率与出错的概率/增加线程状态切换与出错的概率
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {  //
                        e.printStackTrace();
                    }
                    //打印当前正在售票的线程名,并且票数-1
                    System.out.println(getName()+":"+tickets--);
//                }
                if(tickets <= 0) break;//注意,死循环设置的出口是没票的时候就停止
            //PS: 自定义逻辑: 即使同步了排序,但一个线程拿到最后一张票,但是其它第线程没有票了就不会排队了,同时抢占最后一张票,超卖
            }
        }  //tab后移代码
    }
}

class Dog{
}